package org.zizi.manager.impl;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.zizi.dao.BaseDao;
import org.zizi.db.EasySql;
import org.zizi.db.build.DataSourceBuilder;
import org.zizi.db.build.EasySqlBuilder;
import org.zizi.db.build.EasySqlConfig;
import org.zizi.manager.Manager;
import org.zizi.util.Options;

public class DaoManager implements Manager
{
	private static Logger log = Logger.getLogger(ActionManager.class);
	
	private static final String DATABASE_TYPE = "DatabaseType";
	private static final String DATABASE_SERVER = "DatabaseServer";
	private static final String DATABASE_PORT = "DatabasePort";
	private static final String DATABASE_NAME = "DatabaseName";
	private static final String DATABASE_USER = "DatabaseUser";
	private static final String DATABASE_PASSWORD = "DatabasePassword";
	private static final String DATABASE_MAX_CONNECTIONS = "DatabaseMaxConnections";
	
	private static final String DATABASE_CHARSET = "DatabaseCharset";
	private static final String JAVA_RUNTIME_CHARSET = "JavaRuntimeCharset";
	
	private static final int TRANSACTION_READ_COMMITTED = 2;
	
	private Map<Class<?>, Class<?>> daos = new HashMap<Class<?>, Class<?>>();
	
	private EasySqlConfig config;
	private EasySql esql;
	private DataSource source;
	
	private boolean initialized = false;
	
	public void initialize(Options options) throws Exception
	{
		if (initialized) return;
		initialized = true;
		
		String type = options.get(DATABASE_TYPE, String.class);
		String server = options.get(DATABASE_SERVER, String.class);
		Integer port = options.get(DATABASE_PORT, Integer.class);
		String name = options.get(DATABASE_NAME, String.class);
		String user = options.get(DATABASE_USER, String.class);
		String password = options.get(DATABASE_PASSWORD, String.class);
		Integer connections = options.get(DATABASE_MAX_CONNECTIONS, Integer.class, null);
		
		String javaCharset = options.get(JAVA_RUNTIME_CHARSET, String.class, null);
		String databaseCharset = options.get(DATABASE_CHARSET, String.class, null);
		
		config = new EasySqlConfig();
		config.setDatabase(type);
		config.setServer(server);
		config.setPort(port);
		config.setName(name);
		config.setUser(user);
		config.setPassword(password);
		config.setMax(connections);
		
		esql = EasySqlBuilder.build(type);
		source = DataSourceBuilder.build(config);
		
		esql.charset().setJavaCharset(javaCharset);
		esql.charset().setDatabaseCharset(databaseCharset);
	}

	public void destory()
	{
	}
	
	public void register(Class<?> type)
	{
		for (Class<?> i : type.getInterfaces())
		{
			daos.put(i, type);
		}
		
		daos.put(type, type);
		
		log.info("注册Dao：" + type.getName());
	}
	
	public <T> T getDao(Class<T> type)
	{
		try
		{
			Class<?> clazz = daos.get(type);
			
			Object obj = clazz.newInstance();
			((BaseDao)obj).setEasySql(esql);
			
			return type.cast(obj);
		}
		catch(Exception e)
		{
			log.error("获取Dao错误：", e);
			return null;
		}
	}
	
	/** 开始事务 */
	public void begin() throws Exception
	{
		try
		{
			esql.begin(TRANSACTION_READ_COMMITTED, source);
		}
		catch (Exception e)
		{
			throw new Exception("开始事务错误：", e);
		}
	}
	
	/** 提交事务 */
	public void commit() throws Exception
	{
		try
		{
			esql.commit();
		}
		catch (Exception e)
		{
			throw new Exception("提交事务错误：", e);
		}
	}
	
	/** 结束事务：若未提交，则回滚 */
	public void end()
	{
		try
		{
			esql.end();
		}
		catch (Exception e)
		{
		}
	}
}
